#ifndef DOFS_H
#define DOFS_H

#include "Point.h"

/**
 * @brief 自由度类，继承几何点类，新添一个全局编号；
 */
template<unsigned int DIM>
class Dofs : public Point<DIM>
{
public:
    /**
     * @brief     生成一个指定维度自由度，各个分量均为０的自由度，全局编号为０；  
     */
    Dofs();

    Dofs(const std::initializer_list<double>, int d=2);

    /**
     * @brief Construct a new Point object by num array in c++/c;
     *        生成一个指定维度自由度，各个分量与数组各分量相同的自由度,并且指定全局编号；
     */
    Dofs(const std::vector<double>, int d=2);

    /**
     * @brief Destroy the Dofs object
     */
    ~Dofs();

    /**
     * @brief Set the Global Index object
     */
    void SetGlobalIndex(const int);

    /**
     * @brief Set and get the Global Index object
     * @return int& 全局编号的引用；
     */
    int& GlobalIndex() {return  _GlbIdx;};

    /**
     * @brief 重载下标运算符operator[]，可以用p[0]表示已经声明的自由度的第一个维度；
     * 
     * @param d 指定维度；
     * @return double& 返回一个实数类型。
     */
    double& operator[](const unsigned int d);
    /**
     * @brief 重载输出运算符operator<<;
     * 
     * @tparam D 该几何点维度；
     * @param os 输出类；
     * @param p 待输出点；
     * @return std::ostream& 输出类的引用；
     */
    template<unsigned int D>
    friend std::ostream& operator<<(std::ostream&, const Dofs<D> &);
private:
    int _GlbIdx;
};

template<unsigned int DIM>
Dofs<DIM>::Dofs()
{
    _GlbIdx = 0;
};


template<unsigned int DIM>
Dofs<DIM>::Dofs(const std::initializer_list<double> dofs_list,int gl):_GlbIdx(gl)
{
    std::initializer_list<double>::const_iterator i_begin = dofs_list.begin();
    std::initializer_list<double>::const_iterator i_end = dofs_list.end();
    std::copy(i_begin, i_end, Point<DIM>::_value);
};

template<unsigned int DIM>
Dofs<DIM>::Dofs(const std::vector<double> dofs_vector,int gl):_GlbIdx(gl)
{
    std::vector<double>::const_iterator i_begin = dofs_vector.begin();
    std::vector<double>::const_iterator i_end = dofs_vector.end();
    std::copy(i_begin, i_end, Point<DIM>::_value);
};

template<unsigned int DIM>
double& Dofs<DIM>::operator[](const unsigned int d)
{
    return Point<DIM>::_value[d];
}

template<unsigned int DIM>
Dofs<DIM>::~Dofs()
{
};

template<unsigned int DIM>
void Dofs<DIM>::SetGlobalIndex(const int gl)
{
    _GlbIdx = gl;
};

template<unsigned int D>
std::ostream& operator<<(std::ostream& os, const Dofs<D> & dof)
{
    os << dof._GlbIdx << " : ";
    os << "( ";
    for (unsigned int d = 0; d < D - 1; d++)
    {
        os << dof.Point<D>::_value[d] << " , ";
    }
    os << dof.Point<D>::_value[D - 1] << " )";
    return os;
}


#endif /* DOFS_H */
